--- id: TASK-010 title: 'jj (jujutsu) compatibility: bookmark-mode releases + migration guide' status: "\U0001F3C1 Done" assignee: [] created_date: '2026-06-19 06:04' updated_date: '2026-06-19 19:48' labels: - feature dependencies: [] priority: high ordinal: 10000 --- ## Description Make custard's release/tap pipeline and version display work for repos using jj (jujutsu) instead of git. jj can't create git tags, so releases must trigger off bookmarks (git branches) instead. Per-repo .custard.yaml gains brew.source: tag (default, git) | bookmark (jj), plus brew.bookmark_prefix (default 'release/'). A repo is in ONE mode at a time; switching is an explicit config flip. Tag mode = current behavior, untouched. Bookmark mode: webhook triggers on refs/heads/vX.Y.Z, version = stripped name; downgrade guard compares against highest release bookmark; version pill + refs page read the bookmark's tip commit subject as the label (bookmarks have no annotated message). Also ship: MIGRATION guide (git tags -> jj bookmarks, intentional switchover) and a jj usage doc covering how to use jj against soft-serve + how each jj operation shows up in custard. Design spec drafted under docs/superpowers/specs/. ## Acceptance Criteria - [ ] #1 brew.source config field (tag|bookmark) parsed from .custard.yaml, default tag, existing repos unchanged - [ ] #2 Bookmark-mode webhook triggers only on configured prefix + semver; tags ignored in bookmark mode; main/feature pushes never trigger - [ ] #3 Publish splits archive-ref from version; git archive runs against the bookmark branch in bookmark mode - [ ] #4 Downgrade guard is mode-aware: compares against highest semver of the active kind only - [ ] #5 Version pill + refs page recognize release bookmarks, using tip commit subject as the label - [ ] #6 Unit tests: prefix+semver extraction, mode-aware highest-version incl. downgrade rejection, tip-subject label, bookmark-mode webhook - [ ] #7 MIGRATION guide + jj usage/custard-effect doc written and linked from README